"use strict";

//  Components.utils.import("chrome://global/content/contentAreaUtils.js")
    //mponents.utils.import("chrome://viewsosource/locale/utility.jsm")
Components.utils.import("resource://viewsosource/modules/utility.jsm")

 if ("undefined" == typeof(viewSoso)) {
    var viewSoso = {

  orgStateChange : null,    // .gViewSourceUtils.viewSourceProgressListener.onStateChange
  virtualStateChange : function(aProgress, aRequest, aFlag, aStatus)
  {
    // once it's done loading...
    if(aFlag & this.mnsIWebProgressListener.STATE_STOP)
    if(aStatus) //  NS_ERROR_DOCUMENT_NOT_CACHED...
    try {
//        dump("_dvk_dbg_, onStateChange, code:\t"); dump(aStatus); dump("\n");
        window.setTimeout(
            function(aURL, aPageDescriptor, aDocument)
            {
                top.gViewSourceUtils.openInInternalViewer(aURL, aPageDescriptor, aDocument, 0);
            }, 0, this.data.url,
                this.data.pageDescriptor,
                this.data.doc );
    }
    finally {
        this.destroy();
    }
    else return viewSoso.orgStateChange.call(this, aProgress, aRequest, aFlag, aStatus);
    return 0;
  },

  getCurrentURI : function (aspec, abase)
  {
  //    are the currentDocumentChannel and the front documents equal to each other ?
    var loadFromURL = false;
    const theregex = /(#|\?).*$/;   // cut hash and query
    //    currentURI = webNav.currentURI.spec;
    let docShell = gBrowser.selectedBrowser.docShell;
    //  webNav.QueryInterface(Components.interfaces.nsIDocShell);
    //    let thehost = docShell.currentDocumentChannel.URI.host;
    let thevalue = docShell.currentDocumentChannel.URI.spec;
        thevalue = thevalue.replace(/#.*$/, ""); //	cut hash
    if((thevalue != abase.replace(/#.*$/, ""))
            || (thevalue != aspec.replace(/#.*$/, "")))
    {
        thevalue = docShell.currentDocumentChannel.URI.spec;
        loadFromURL = true;
    }
    
    if(loadFromURL) return thevalue
        else return null;
  },

 partialInExternalEditor : function(aspec, adoc)
 {
    top.gViewSourceUtils.openInExternalEditor(
            aspec, null, adoc, 0,
        function(aresult, adata)
        {   if(!aresult)
            {
    //  if occurrence of failure return to internal viewer
               window.setTimeout(viewSoso.viewPartialSourceAsSel, 1);
        }   }
    )
 },

} } //  viewSoso

//  prototype from BrowserViewSourceOfDocument of chrome://browser/content/browser.xul
 viewSoso.openWin = function(aDocument)
 {    
    var pageCookie  = null;
    var currentURI  = "about:blank";
    var loadFromURL = false;
    var webNav;

    // Get the nsIWebNavigation associated with the document
    try {
      // Get the DOMWindow for the requested document.  If the DOMWindow
      // cannot be found, then just use the content window...
      //
      // XXX:  This is a bit of a hack...
        let win = aDocument.defaultView;
        if (win === window) win = content;

        let ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
        webNav = ifRequestor.getInterface(Components.interfaces.nsIWebNavigation);
    }
    catch(err)
    { // If nsIWebNavigation cannot be found, just get the one for the whole window...
        webNav = getWebNavigation();
    }

    if(webNav) webNav.stop(Components.interfaces.nsIWebNavigation.STOP_NETWORK);
    //  webNav.stop(Components.interfaces.nsIWebNavigation.STOP_CONTENT)

  //    are the currentDocumentChannel and the front documents equal to each other ?
    try {
        currentURI = webNav.currentURI.spec;
        var thevalue = viewSoso.getCurrentURI(currentURI, aDocument.baseURIObject.spec);
        if(thevalue)
        {
            currentURI = thevalue;
            loadFromURL = true;
        }        
    }
    catch (err)
    {
      Components.utils.reportError(err)
    }

    if(!loadFromURL)
    try {
        let PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor);  
        pageCookie = PageLoader.currentDescriptor;
    }
    catch(err) {
      // If no page descriptor is available, just use the view-source URL...
    }

//  main charge:
    if(Services.prefs.getBoolPref("view_source.editor.external"))
    {
        top.gViewSourceUtils.openInExternalEditor(currentURI, pageCookie, aDocument, 0);
    }
    else
        top.gViewSourceUtils.openInInternalViewer(currentURI, pageCookie, aDocument, 0);
//    top.gViewSourceUtils.viewSource(currentURI, pageCookie, aDocument);
//  original version:   viewSource( webNav.currentURI.spec , pageCookie, aDocument);
 }   //    BrowserViewSourceOfDocument(aDocument);

    //  nsContextMenu from nsContextMenu.js
 viewSoso.viewPartialSourceAsSel = function()
 {
    var focusedWindow = document.commandDispatcher.focusedWindow;
    if (focusedWindow === window) focusedWindow = content;

    var currentURI = null;
    var docCharset = null;
    if (focusedWindow.document)
    try {
        let thedoc = focusedWindow.document;
        docCharset = "charset=" + thedoc.characterSet;
        currentURI = thedoc.documentURI;
        let thevalue = viewSoso.getCurrentURI(currentURI, thedoc.baseURIObject.spec);
        if(thevalue) currentURI = thevalue;
    }
    catch (err)
    {
        Components.utils.reportError(err)
    }

    var reference = focusedWindow.getSelection();
    if((!reference) || (reference.isCollapsed))
            throw { name: "NS_ERROR_NOT_AVAILABLE",
                    message : "Selection is not reached." };

    // currentURI is unused (and play nice for fragments generated via XSLT too)
    //  needs for test btn of tool dialog
    window.openDialog( "chrome://global/content/viewPartialSource.xul",
                    "_blank", "scrollbars,resizable,chrome,dialog=no",
                    currentURI, docCharset, reference, 'selection');
 }

//  menuitem id="context-viewpartialsource-selection" 
 viewSoso.partialWin = function(atarget)
 {
    var mnsIWebBrowserPersist = Components.interfaces.nsIWebBrowserPersist;
    if(Services.prefs.getBoolPref("view_source.editor.external"))

    try {   //  this.target.ownerDocument
    var focusedWindow = document.commandDispatcher.focusedWindow;

    if(focusedWindow === window) focusedWindow = content;

    if((!focusedWindow) && (atarget))
            focusedWindow = atarget.ownerDocument.defaultView;

    var reference   = focusedWindow.getSelection();
    var thedoc      = focusedWindow.document;
    // "charset=" + thedoc.characterSet;
    var docCharset  = thedoc.characterSet || "utf-8";
    var contentType = thedoc.contentType || "text/html";
    //  var range = selection.getRangeAt(0);
    //  var ancestorContainer = range.commonAncestorContainer;
        var thancestor = reference.getRangeAt(0).commonAncestorContainer;
    //  if(!aURI) aURI = thedoc.documentURIObject;
    var thefile = utilityViewSoso.getTemporaryFile(
                    thedoc.documentURIObject, contentType, window);
    //  dump("_dvk_dbg_, file:\t"); dump(thefile.path); dump("\n");
        
    if((thancestor === thedoc.body) || (thancestor === thedoc.documentElement))
    {
    //       this.viewSourceProgressListener.file = thefile;
        var webBrowserPersist = Components
                .classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
                .createInstance(mnsIWebBrowserPersist);
    // the default setting is to not decode. we need to decode.
        webBrowserPersist.persistFlags = mnsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES
                                    | mnsIWebBrowserPersist.PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS
                                    | mnsIWebBrowserPersist.PERSIST_FLAGS_IGNORE_IFRAMES
                                    | mnsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE ;
        webBrowserPersist.saveDocument(thedoc, thefile, null, null, null, null);
    }
    else {
        let theval = thancestor.outerHTML || thancestor.textContent;
        utilityViewSoso.element2file(theval, thefile, docCharset);
    }

    //  register the file to be deleted on app exit
    Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
                .getService(Components.interfaces.nsPIExternalAppLauncher)
                .deleteTemporaryFileOnExit(thefile);

    let thespec = "file://" + thefile.path;
//    top.gViewSourceUtils.openInExternalEditor( thespec, null, thedoc, 0, callback );
    //  little counterpart of asynchronous calling
    window.setTimeout(viewSoso.partialInExternalEditor, 1, thespec, thedoc);

    }
    catch(err)
    {
        Components.utils.reportError(err)
    }

    else viewSoso.viewPartialSourceAsSel();
 }  //  viewSoso.partialWin

 viewSoso.getLocalStorage = 
    "var thejson = {};" +
    "for(let i = 0; i < localStorage.length; ++i)" +
    "{  let thekey = localStorage.key(i);" +
    "   let theval = localStorage.getItem(thekey);" +
    "   try {" +
    "       theval = JSON.parse(theval); " +
    "   } catch(err) {} " +
    "   thejson[thekey] = theval; } thejson;";

 viewSoso.storageWin = function(amenu)
 {
    const theregex = /(#|\?).*$/;   // cut hash and query
    var thejson = null;//  contentWindow   contentDocument
    var thedoc = gBrowser.selectedBrowser.contentDocument;
    var contentWindow = gBrowser.selectedBrowser.contentWindow;
    var currentURI = contentWindow.location.href;
    
    try {
    if(thedoc.domain)
    {
        var contentSandbox = new Components.utils.Sandbox(contentWindow,
            { sandboxPrototype: contentWindow, wantXrays: false });
        let thelen = Components.utils.evalInSandbox("localStorage.length", contentSandbox, "1.8");
        if(thelen)
        {
            thejson = Components.utils.evalInSandbox(viewSoso.getLocalStorage, contentSandbox, "1.8");
        }
    }
    else
    {
        let princip = Services.scriptSecurityManager.getCodebasePrincipal(thedoc.documentURIObject);
        var theStorage = Services.domStorageManager.getLocalStorageForPrincipal(princip, "");
            currentURI = thedoc.documentURIObject.spec;
            
        if(theStorage.length)
        {
            thejson = {};
            for(let i = 0; i < theStorage.length; ++i)
            {
                let thekey = theStorage.key(i);
                let theval = theStorage.getItem(thekey);
                try {
                    theval = JSON.parse(theval);
                }
                catch(err) {}
                thejson[thekey] = theval;
            }
    //          contentWindow.console.info(thejson);
        }
    }
    }
    catch(err)
    {
        Components.utils.reportError(err)
    }

    currentURI = currentURI.replace(theregex, ""); // cut hash and query

    if(thejson)
    {
    if(Services.prefs.getBoolPref("view_source.editor.external"))
    {
        var thecharset = "utf-8";  //  test some Cyrillic
        var contentType = "application/json";
        var thefile = utilityViewSoso.getTemporaryFile(
                        thedoc.documentURIObject, contentType, window);

            //  set format of object
            thejson = JSON.stringify(thejson, null, '\t');
            utilityViewSoso.element2file(thejson, thefile, thecharset);

        //  register the file to be deleted on app exit
        Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
                    .getService(Components.interfaces.nsPIExternalAppLauncher)
                    .deleteTemporaryFileOnExit(thefile);

        let thespec = "file://" + thefile.path;
        thedoc = { characterSet: thecharset, contentType : contentType };

    //  little counterpart of asynchronous calling
    //  window.setTimeout(viewSoso.partialInExternalEditor, 1, thespec, thedoc);
        top.gViewSourceUtils.openInExternalEditor(thespec, null, thedoc, 0);
    }
    else {  //  default: charset=utf-8
    //  second null is :  charset = "charset=" + aDocument.characterSet;
        let docCharset  = "charset=" + (thedoc.characterSet || "utf-8");
        window.openDialog( "chrome://global/content/viewPartialSource.xul",
                    "_blank", "scrollbars,resizable,chrome,dialog=no",
                    currentURI, docCharset, thejson, 'json');

    }
    }
    else
        Services.prompt.alert(window, currentURI, amenu.value);
 }
